﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Forms;
using Caliburn.Micro;
using MIXer.Contracts.ViewModels;
using MIXer.Core.Contracts;
using MIXer.Core.Domain;
using MIXer.Ch9;

namespace MIXer.ViewModels
{
    [Export(typeof(IRenamerViewModel))]
    public class RenamerViewModel : Tab, IRenamerViewModel
    {
        #region Fields
        private string _folderLocation;
        private BindableCollection<SessionFile> _files;
        private TechEvent _selectedEvent;
        private string _nameFormat;
        #endregion

        #region Constructors
        public RenamerViewModel()
            : base("Renamer")
        {
            NameFormat = "$code_$title"; // default
        }
        #endregion

        #region Methods
        public void OpenFolderDialog()
        {
            var dialog = new FolderBrowserDialog();
            var result = dialog.ShowDialog();

            if (result == DialogResult.OK)
            {
                FolderLocation = dialog.SelectedPath;
            }
        }
        public void GetFiles()
        {
            Busy("Getting file names from folder...");

            var folder = Directory.GetFiles(FolderLocation);

            Files = new BindableCollection<SessionFile>(folder.Select(f => new SessionFile
            {
                FileName = Path.GetFileName(f),
                Extension = Path.GetExtension(f),
                FullName = f,
                FileNameWithoutExtension = Path.GetFileNameWithoutExtension(f),
                IsSelected = true
            }).ToList());

            Free();
        }
        public async void RenameFiles()
        {
            Busy("Renaming files...");

            var selectedFiles = (from f in Files
                                 where f.IsSelected == true
                                 select f).ToList();

            var sessions = await Ch9RssFeed.GetFilesFromFeed(SelectedEvent.Links[0].Address, SelectedEvent.EventCode);

            Parallel.ForEach(selectedFiles, file =>
            {
                var session = (from s in sessions
                               where s.SessionCode == file.FileNameWithoutExtension
                               select s).FirstOrDefault();

                if (session != null)
                {
                    string path = Path.GetDirectoryName(file.FullName);
                    string oldFileName = file.FullName;

                    string newFileName = NameTransformer.Transform(NameFormat, session);

                    file.FileName = newFileName + file.Extension;
                    file.FileNameWithoutExtension = newFileName;
                    file.FullName = Path.Combine(path, file.FileName);

                    try
                    {
                        File.Move(oldFileName, file.FullName);
                    }
                    catch { }
                }
            });

            FilesContentChanged();

            Free();
        }
        public void SelectAll()
        {
            foreach (var file in Files)
            {
                file.IsSelected = true;
            }

            FilesContentChanged();
        }
        public void DeSelectAll()
        {
            foreach (var file in Files)
            {
                file.IsSelected = false;
            }

            FilesContentChanged();
        }
        public void FileCheckChanged(SessionFile file)
        {
            if (file != null)
            {
                FilesContentChanged();
            }
        }
        public void EventSelectionChanged(TechEvent techEvent)
        {
            SelectedEvent = techEvent;
        }
        private void FilesContentChanged()
        {
            NotifyOfPropertyChange(() => CanSelectAll);
            NotifyOfPropertyChange(() => CanDeSelectAll);
            NotifyOfPropertyChange(() => CanRenameFiles);
        }
        #endregion

        #region Properties
        public string FolderLocation
        {
            get { return _folderLocation; }
            set
            {
                _folderLocation = value;
                NotifyOfPropertyChange(() => FolderLocation);
                NotifyOfPropertyChange(() => CanGetFiles);
            }
        }
        public string NameFormat
        {
            get { return _nameFormat; }
            set
            {
                _nameFormat = value;
                NotifyOfPropertyChange(() => CanRenameFiles);
            }
        }
        public TechEvent SelectedEvent
        {
            get { return _selectedEvent; }
            set
            {
                _selectedEvent = value;
                NotifyOfPropertyChange(() => CanRenameFiles);
            }
        }
        public BindableCollection<SessionFile> Files
        {
            get { return _files; }
            set
            {
                _files = value;
                NotifyOfPropertyChange(() => Files);
                FilesContentChanged();
            }
        }
        public IList<TechEvent> Events
        {
            get { return AvailableEventsProvider.AvailableEvents; }
        }
        public string AvailableTokens
        {
            get
            {
                StringBuilder tokens = new StringBuilder();
                foreach (var token in NameTransformer.AvailableTokens)
                {
                    if (tokens.Length > 0) tokens.Append(", ");
                    tokens.Append(token);
                }

                return tokens.ToString();
            }
        }

        #region Conditional Properties
        public bool CanGetFiles
        {
            get { return !String.IsNullOrWhiteSpace(FolderLocation); }
        }
        public bool CanSelectAll
        {
            get { return _files != null && _files.Any(f => !f.IsSelected); }
        }
        public bool CanDeSelectAll
        {
            get { return _files != null && _files.Any(f => f.IsSelected); }
        }
        public bool CanRenameFiles
        {
            get { return _files != null && _files.Any(f => f.IsSelected) && SelectedEvent != null && !String.IsNullOrEmpty(NameFormat); }
        }
        #endregion

        #region Providers
        [Import(typeof(IAvailableEventsProvider), AllowDefault = true)]
        public IAvailableEventsProvider AvailableEventsProvider { get; set; }

        [Import(typeof(INameTransformer), AllowDefault = true)]
        public INameTransformer NameTransformer { get; set; }
        #endregion
        #endregion
    }
}
